#ifndef YHAIDA_TCPSERVER_H
#define YHAIDA_TCPSERVER_H
#include "../base/Utils.h"
#include "Callbacks.h"
#include "TcpConnection.h"
#include "InetAddress.h"
#include "../logging/Logging.h"
#include "SocketsOps.h"
#include <memory>
#include <map>
#include <functional>
namespace yhaida
{
    //前向声明
    class Acceptor;
    class EventLoop;
    class EventLoopThreadPool;
    /*
    TcpServer管理TcpServerConnection
    本质就是Acceptor类
    */
    class TcpServer : Utils::nocapyable
    {
    public:
        typedef std::map<std::string, TcpConnectionPtr> ConnectionMap;
        typedef std::function<void(EventLoop *)> ThreadInitCallback;
        enum Option
        {
            kNoReusePort,
            kReusePort,
        };

    public:
        TcpServer(EventLoop *loop, const InetAddress &listenAddr,Option option = kNoReusePort);
        ~TcpServer();

        void setThreadNum(int numThreads);
        void setThreadInitCallback(const ThreadInitCallback &cb)
        {
            _threadInitCallback = cb;
        }

        void start();
        //开放给用户 连接和读
        void setConnectionCallback(const ConnectionCallback &cb)
        {
            _connectionCallback = cb;
        }
        void setMessageCallback(const MessageCallback &cb)
        {
            _messageCallback = cb;
        }
        void setWriteCompleteCallback(const WriteCompleteCallback &cb)
        {
            _writeCompleteCallback = cb;
        }

        EventLoop* getLoop() const { return _mainEventLoop; }
    private:
        void newConnection(int sockfd, const InetAddress &addr);
        void removeConnection(const TcpConnectionPtr &conn);
        void removeConnectionInLoop(const TcpConnectionPtr &conn);

        bool _start;
        int _nextConnId;

        const std::string _name;

        EventLoop *_mainEventLoop;
        //想要管理TCP，则必须管理一个accptor类，因为这是产生fd（TCP）
        std::unique_ptr<Acceptor> _acceptor;
        std::unique_ptr<EventLoopThreadPool> _threadPool;
        ConnectionMap _connections;

        ConnectionCallback _connectionCallback;
        MessageCallback _messageCallback;
        WriteCompleteCallback _writeCompleteCallback;
        ThreadInitCallback _threadInitCallback;
    };

}

#endif